﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.SqlClient;
using System.Globalization;
using Infraestrutura.Repositorios.SQL;
using Model.Clientes;
using Model.Produtos;
using Model.Tipologias;

namespace Model.Requisicoes
{
    public class RequisicaoService : RepositorioSQL<Requisicao>, IRequisicaoService
    {
        public RequisicaoService()
        {
            Tabela = "Requisicoes";
            LigacaoBD = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
        }
        
        public Requisicao ObterPorNumeroRequisicao(Int64 numeroRequisicao)
        {
            return ObterPorChave(String.Format("@NumeroRequisicao={0}", numeroRequisicao));
        }

        public IList<Requisicao> ObterTodosPorUnidadeData(Int64 idUnidade, DateTime dataRequisicao)
        {
            return ObterLista(String.Format("proc_RequisicoesLoadByUnidadeData @IdUnidade={0}, @DataRequisicao='{1}'",
                                 idUnidade, dataRequisicao.ToString("yyyy-MM-ddTHH:mm:ss")));
        }

        protected override string ObterParametrosInserir(Requisicao item)
        {
            return String.Format("@NumeroRequisicao={0}, @IdUnidade={1}, @DataRequisicao='{2}', @Gerente='{3}', @ResponsavelRecepcaoProduto='{4}'",
                                  item.NumeroRequisicao, 
                                  item.Unidade.IdUnidade,                            
                                  item.DataRequisicao.ToString("yyyy-MM-ddTHH:mm:ss"),
                                  item.Gerente, item.ResponsavelRecepcaoProduto);
        }


        protected override string ObterParametrosApagar(Requisicao item)
        {
            return String.Format("@NumeroRequisicao={0}",
                                  item.NumeroRequisicao);
        }

        protected override Requisicao CarregarDados(System.Data.SqlClient.SqlDataReader dataReader, Requisicao item)
        {
            item.NumeroRequisicao = Convert.ToInt64(dataReader["NumeroRequisicao"]);
            item.DataRequisicao = Convert.ToDateTime(dataReader["DataRequisicao"]);
            item.Gerente = dataReader["Gerente"].ToString();
            item.ResponsavelRecepcaoProduto = dataReader["ResponsavelRecepcaoProduto"].ToString();
            
            item.Unidade = new Unidade();
            item.Unidade.IdUnidade = Convert.ToInt64(dataReader["IdUnidade"]);
            item.Unidade.Servico = Convert.ToBoolean(dataReader["ServicoUnidade"]);
            if(!Convert.IsDBNull(dataReader["UnidadePai"]))
                item.Unidade.UnidadePai = new Unidade() { IdUnidade = Convert.ToInt64(dataReader["UnidadePai"]) };

            item.Unidade.Cliente = new Cliente();
            item.Unidade.Cliente.IdCliente = Convert.ToInt64(dataReader["IdCliente"]);
            item.Unidade.Cliente.Nome = dataReader["NomeCliente"].ToString();
            item.Unidade.Designacao = dataReader["DesignacaoUnidade"].ToString();
            
            return item;
        }


        #region Linha Requisicao

        public LinhaRequisicao ObterLinhaPorRequisicaoRefeicaoProduto(Int64 numeroRequisicao, Int64 idRefeicaoContratada, Int64 idProduto)
        {
            Requisicao requisicao = ObterPorNumeroRequisicao(numeroRequisicao);
              
            return ObterLinhaPorRequisicaoRefeicaoProduto(requisicao, idRefeicaoContratada, idProduto);
        }

        public LinhaRequisicao ObterLinhaPorRequisicaoRefeicaoProduto(Requisicao requisicao, Int64 idRefeicaoContratada, Int64 idProduto)
        {
            LinhaRequisicao item = null;

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {

                SqlCommand command = new SqlCommand(
                   String.Format("exec proc_RequisicoesLinhaLoadByPrimaryKey @IdProduto={0}, @IdRefeicaoContratada={1}, @NumeroRequisicao={3}",
                                  idProduto, idRefeicaoContratada, requisicao.NumeroRequisicao),
                   sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    item = new LinhaRequisicao();
                    item = CarregarDados(reader, item, requisicao);
                }

                reader.Close();
            }

            return item;

        }

        public IList<LinhaRequisicao> ObterlinhasPorRequisicao(Int64 numeroRequisicao)
        {
            Requisicao requisicao = ObterPorNumeroRequisicao(numeroRequisicao);

            return ObterlinhasPorRequisicao(requisicao);
        }
        
        public IList<LinhaRequisicao> ObterlinhasPorRequisicao(Requisicao requisicao)
        {
            IList<LinhaRequisicao> lista = new List<LinhaRequisicao>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RequisicoesLinhaLoadByRequisicao @NumeroRequisicao={0}",
                                 requisicao.NumeroRequisicao,
                                 sqlConnection));

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                LinhaRequisicao item = null;
                while (reader.Read())
                {
                    item = new LinhaRequisicao();
                    lista.Add(CarregarDados(reader, item, requisicao));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<LinhaRequisicao> ObterlinhasPorRequisicaoRefeicao(Int64 numeroRequisicao, Int64 idRefeicaoContratada){
            Requisicao requisicao = ObterPorNumeroRequisicao(numeroRequisicao);

            return ObterlinhasPorRequisicaoRefeicao(requisicao, idRefeicaoContratada);
        }
        
        public IList<LinhaRequisicao> ObterlinhasPorRequisicaoRefeicao(Requisicao requisicao, Int64 idRefeicaoContratada)
        {
            IList<LinhaRequisicao> lista = new List<LinhaRequisicao>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RequisicoesLinhaLoadByRequisicaoRefeicaoContratada @NumeroRequisicao={0}, @idRefeicaoContratada={1}",
                                 requisicao.NumeroRequisicao,
                                 idRefeicaoContratada,
                                 sqlConnection));

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                LinhaRequisicao item = null;
                while (reader.Read())
                {
                    item = new LinhaRequisicao();
                    lista.Add(CarregarDados(reader, item, requisicao));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<LinhaRequisicao> ObterlinhasTodosProdutosPorRequisicaoRefeicao(Int64 numeroRequisicao, Int64 idRefeicaoContratada){
            Requisicao requisicao = ObterPorNumeroRequisicao(numeroRequisicao);

            return ObterlinhasTodosProdutosPorRequisicaoRefeicao(requisicao, idRefeicaoContratada);
        }

        public IList<LinhaRequisicao> ObterlinhasTodosProdutosPorRequisicaoRefeicao(Requisicao requisicao, Int64 idRefeicaoContratada)
        {
            IList<LinhaRequisicao> lista = new List<LinhaRequisicao>();

            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RequisicoesLinhaLoadAllProdutos_O1 @NumeroRequisicao={0}, @idRefeicaoContratada={1}",
                                 requisicao.NumeroRequisicao,
                                 idRefeicaoContratada),
                                 connection);

                command.Connection.Open();

                SqlDataReader reader = command.ExecuteReader();

                LinhaRequisicao item = null;
                while (reader.Read())
                {
                    item = new LinhaRequisicao();
                    lista.Add(CarregarDados(reader, item, requisicao));
                }

                reader.Close();
            }

            return lista;
        }


        public LinhaRequisicao Actualiza(LinhaRequisicao item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RequisicoesLinhaUpdate {0}", ObterParametrosActualizar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteScalar();
            }

            return item;
        }

        public IList<LinhaRequisicao> Actualiza(IList<LinhaRequisicao> items)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction();

                SqlCommand command = null;
                foreach (LinhaRequisicao item in items)
                {
                    command = new SqlCommand(
                        String.Format("exec proc_RequisicoesLinhaUpdate {0}", ObterParametrosInserir(item)),
                        connection, transaction);

                    item.AtribuirChave(command.ExecuteScalar());
                }
                transaction.Commit();
            }

            return items;
        }

        public LinhaRequisicao Insere(LinhaRequisicao item){
           
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RequisicoesLinhaInsert {0}", ObterParametrosInserir(item)),
                    connection);

                command.Connection.Open();
                item.AtribuirChave(command.ExecuteScalar());
            }

            return item;
        }

        public void Apaga(LinhaRequisicao item){
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RequisicoesLinhaDelete {0}", ObterParametrosApagar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }

        protected String ObterParametrosApagar(LinhaRequisicao item)
        {
            return String.Format("@IdProduto={0}, @IdRefeicaoContratada={1}, @NumeroRequisicao={2}",
                                 item.Produto.IdProduto, item.IdRefeicaoContratada, item.Requisicao.NumeroRequisicao);
        }


        protected String ObterParametrosActualizar(LinhaRequisicao item)
        {
            return ObterParametrosInserir(item);
        }

        protected String ObterParametrosInserir(LinhaRequisicao item)
        {
            return String.Format("@IdProduto={0}, @IdRefeicaoContratada={1}, @NumeroRequisicao={2}, @Quantidade={3}, @NomeProduto='{4}', @DescricaoProduto='{5}', @CodUnidadeMedida='{6}', @PrecoCusto={7}, @TotalCusto={8}",
                                     item.Produto.IdProduto,
                                     item.IdRefeicaoContratada,
                                     item.Requisicao.NumeroRequisicao,
                                     item.Quantidade.ToString(NumberFormatInfo.InvariantInfo),
                                     item.NomeProduto,
                                     item.DescricaoProduto,
                                     item.UnidadeMedida.Codigo,
                                     item.PrecoCusto.ToString(NumberFormatInfo.InvariantInfo),
                                     item.TotalCusto.ToString(NumberFormatInfo.InvariantInfo));
        }


        protected LinhaRequisicao CarregarDados(SqlDataReader dataReader, LinhaRequisicao item, Requisicao requisicao)
        {
            item.Produto = new Produto();
            item.Produto.IdProduto = Convert.ToInt64(dataReader["IdProduto"]);
            item.Produto.Nome = dataReader["NomeProduto"].ToString();
            item.Produto.Descricao = dataReader["DescricaoProduto"].ToString();
            item.Produto.PrecoCusto = Convert.ToDecimal(dataReader["PrecoCusto"]);
            item.Produto.UnidadeMedida = new Tipologia()
            {
                Codigo = dataReader["CodUnidadeMedida"].ToString(),
                Descricao = dataReader["DescricaoUMedida"].ToString(),
                DescricaoCurta = dataReader["DescricaoCurtaUMedida"].ToString(),
                Simbolo = dataReader["SimboloUMedida"].ToString(),
                Tipo = dataReader["TipoUMedida"].ToString()
            };
            
            item.Produto.Moeda = new Tipologia()
            {
                Codigo = dataReader["CodMoeda"].ToString(),
                Descricao = dataReader["DescricaoMoeda"].ToString(),
                DescricaoCurta = dataReader["DescricaoCurtaMoeda"].ToString(),
                Simbolo = dataReader["SimboloMoeda"].ToString(),
                Tipo = dataReader["TipoMoeda"].ToString()
            };
            item.Produto.GrupoProduto = new GrupoProduto()
            {
                CodGrupoProduto = dataReader["CodGrupoProduto"].ToString(),
                Descricao = dataReader["DescricaoGrupoProduto"].ToString(),
                Nome = dataReader["NomeGrupoProduto"].ToString()
            };
            item.Produto.GrupoProduto.GrupoPai = new GrupoProduto()
            {
                CodGrupoProduto = dataReader["CodGrupoProdutoPai"].ToString(),
                Descricao = dataReader["DescricaoGrupoProdutoPai"].ToString(),
                Nome = dataReader["NomeGrupoProdutoPai"].ToString()
            };

            item.IdRefeicaoContratada = Convert.ToInt64(dataReader["IdRefeicaoContratada"]);
            item.PrecoCusto = Convert.ToDecimal(dataReader["PrecoCusto"]);

            if (!Convert.IsDBNull(dataReader["TotalCusto"])) 
                item.TotalCusto = Convert.ToDecimal(dataReader["TotalCusto"]);
            
            if(!Convert.IsDBNull(dataReader["Quantidade"]))
                item.Quantidade = Convert.ToDecimal(dataReader["Quantidade"]);
            
            item.NomeProduto = dataReader["NomeProduto"].ToString();
            item.DescricaoProduto = dataReader["DescricaoProduto"].ToString();
            item.Requisicao = requisicao;
            item.UnidadeMedida = new Tipologia(){
                Codigo = dataReader["CodUnidadeMedida"].ToString(),
                Descricao = dataReader["DescricaoUMedida"].ToString(),
                DescricaoCurta= dataReader["DescricaoCurtaUMedida"].ToString(),
                Simbolo = dataReader["SimboloUMedida"].ToString(),
                Tipo = dataReader["TipoUMedida"].ToString()
            };

            return item;
        }

        #endregion
    }
}
